home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / uud.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  11KB  |  554 lines

  1. /* uud - bulletproof version of uudecode */
  2.  
  3. /*
  4.  * Uud -- decode a uuencoded file back to binary form.
  5.  *
  6.  * From the Berkeley original, modified by MSD, RDR, JPHD & WLS.
  7.  * The Atari GEMDOS version compiled with MWC 2.x.
  8.  * The MSDOS version with TurboC.
  9.  * The Unix version with cc.
  10.  * this version is made: 25 Nov 1988.
  11.  * Jan 2 1990: Change system definition and change MSDOS to open the output
  12.  *             file for write binary do cr/lf replacement.
  13.  */
  14.  
  15. #define UNIX  1        /* define one of: UNIX (Minix too!), MSDOS, or GEMDOS */ 
  16.  
  17. #ifdef GEMDOS
  18. #define SYSNAME "gemdos"
  19. #define SMALL 1
  20. #endif
  21. #ifdef MSDOS
  22. #define SYSNAME "msdos"
  23. #define SMALL 1
  24. #endif
  25. #ifdef UNIX
  26. #define SYSNAME "unix"
  27. #endif
  28.  
  29. #include <stdio.h>
  30.  
  31. #ifdef GEMDOS
  32. #include <osbind.h>
  33. #define Error(n)  { Bconin(2); exit(n); }
  34. #else
  35. #define Error(n)  exit(n)
  36. #endif
  37. #ifdef UNIX
  38. #define WRITE      "w"
  39. #else
  40. #define WRITE      "wb"        /* for both MSDOS and GEMDOS!    */
  41. #endif
  42.  
  43. #define loop    while (1)
  44.  
  45. extern FILE *fopen();
  46. extern char *strcpy();
  47. extern char *strcat();
  48.  
  49. char *getnword();
  50.  
  51. #define NCHARS  256
  52. #define LINELEN 256
  53. #define FILELEN 64
  54. #define NORMLEN 60    /* allows for 80 encoded chars per line */
  55.  
  56. #define SEQMAX 'z'
  57. #define SEQMIN 'a'
  58. char seqc;
  59. int first, secnd, check, numl;
  60.  
  61. FILE *in, *out;
  62. char *pos;
  63. char ifname[FILELEN], ofname[FILELEN];
  64. char *source = NULL, *target = NULL;
  65. char blank, part = '\0';
  66. int partn, lens;
  67. int debug = 0, nochk = 0, onedone = 0;
  68. int chtbl[NCHARS], cdlen[NORMLEN + 3];
  69.  
  70. main(argc, argv) int argc; char *argv[];
  71. {
  72.     int mode;
  73.     register int i, j;
  74.     char *curarg;
  75.     char dest[FILELEN], buf[LINELEN];
  76.  
  77.     if (argc < 2) {
  78.         format("Usage: uud [-n] [-d] [-s dir] [-t dir] input-file\n");
  79.         Error(1);
  80.     }
  81.  
  82.     curarg = argv[1];
  83.     
  84.     while (curarg[0] == '-') {
  85.         if (((curarg[1] == 'd') || (curarg[1] == 'D')) &&
  86.             (curarg[2] == '\0')) {
  87.             debug = 1;
  88.         } else if (((curarg[1] == 'n') || (curarg[1] == 'N')) &&
  89.                (curarg[2] == '\0')) {
  90.             nochk = 1;
  91.         } else if (((curarg[1] == 't') || (curarg[1] == 'T')) &&
  92.                (curarg[2] == '\0')) {
  93.             argv++;
  94.             argc--;
  95.             if (argc < 2) {
  96.                 format("uud: Missing target directory.\n");
  97.                 Error(15);
  98.             }
  99.             target = argv[1];
  100.             if (debug)
  101.                 format("Target dir = %s\n",target);
  102.         } else if (((curarg[1] == 's') || (curarg[1] == 'S')) &&
  103.                (curarg[2] == '\0')) {
  104.             argv++;
  105.             argc--;
  106.             if (argc < 2) {
  107.                 format("uud: Missing source directory.\n");
  108.                 Error(15);
  109.             }
  110.             source = argv[1];
  111.             if (debug)
  112.                 format("Source dir = %s\n",source);
  113.         } else if (curarg[1] != '\0') {
  114.             format("uud: Unknown option <%s>\n", curarg);
  115.             Error(15);
  116.         } else
  117.             break;
  118.         argv++;
  119.         argc--;
  120.         if (argc < 2) {
  121.             format("uud: Missing file name.\n");
  122.             Error(15);
  123.         }
  124.         curarg = argv[1];
  125.     }
  126.  
  127.     if ((curarg[0] == '-') && (curarg[1] == '\0')) {
  128.         in = stdin;
  129.         strcpy(ifname, "<stdin>");
  130.     } else {
  131.         if (source != NULL) {
  132.             strcpy(ifname, source);
  133.             strcat(ifname, curarg);
  134.         } else
  135.             strcpy(ifname, curarg);
  136.         if ((in = fopen(ifname, "r")) == NULL) {
  137.             format("uud: Can't open %s\n", ifname);
  138.             Error(2);
  139.         }
  140.         numl = 0;
  141.     }
  142.  
  143. /*
  144.  * Set up the default translation table.
  145.  */
  146.     for (i = 0; i < ' '; i++) chtbl[i] = -1;
  147.     for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j;
  148.     for (i = ' ' + 64; i < NCHARS; i++) chtbl[i] = -1;
  149.     chtbl['`'] = chtbl[' '];    /* common mutation */
  150.     chtbl['~'] = chtbl['^'];    /* an other common mutation */
  151.     blank = ' ';
  152. /*
  153.  * set up the line length table, to avoid computing lotsa * and / ...
  154.  */
  155.     cdlen[0] = 1;
  156.     for (i = 1, j = 5; i <= NORMLEN; i += 3, j += 4)
  157.         cdlen[i] = (cdlen[i + 1] = (cdlen[i + 2] = j));
  158. /*
  159.  * search for header or translation table line.
  160.  */
  161.     loop {    /* master loop for multiple decodes in one file */
  162.         partn = 'a';
  163.         loop {
  164.             if (fgets(buf, sizeof buf, in) == NULL) {
  165.                 if (onedone) {
  166.                     if (debug) format("End of file.\n");
  167.                     exit(0);
  168.                 } else {
  169.                     format("uud: No begin line.\n");
  170.                     Error(3);
  171.                 }
  172.             }
  173.             numl++;
  174.             if (strncmp(buf, "table", 5) == 0) {
  175.                 gettable();
  176.                 continue;
  177.             }
  178.             if (strncmp(buf, "begin", 5) == 0) {
  179.                 break;
  180.             }
  181.         }
  182.         lens = strlen(buf);
  183.         if (lens) buf[--lens] = '\0';
  184. #ifdef SMALL
  185.         if ((pos = getnword(buf, 3))) {
  186.             strcpy(dest, pos);
  187.         } else
  188. #else
  189.         if(sscanf(buf,"begin%o%s", &mode, dest) != 2)
  190. #endif
  191.         {
  192.             format("uud: Missing filename in begin line.\n");
  193.             Error(10);
  194.         }
  195.  
  196.         if (target != NULL) {
  197.             strcpy(ofname, target);
  198.             strcat(ofname, dest);
  199.         } else
  200.             strcpy(ofname, dest);
  201.  
  202.         if((out = fopen(ofname, WRITE)) == NULL) {
  203.             format("uud: Cannot open output file: %s\n", ofname);
  204.             Error(4);
  205.         }
  206.         if (debug) format("Begin uudecoding: %s\n", ofname);
  207.         seqc = SEQMAX;
  208.         check = nochk ? 0 : 1;
  209.         first = 1;
  210.         secnd = 0;
  211.         decode();
  212.         fclose(out);
  213. #ifdef UNIX
  214.         chmod(ofname, mode);
  215. #endif
  216.         onedone = 1;
  217.         if (debug) format("End uudecoding: %s\n", ofname);
  218.     }    /* master loop for multiple decodes in one file */
  219. }
  220.  
  221. /*
  222.  * Bring back a pointer to the start of the nth word.
  223.  */
  224. char *getnword(str, n) register char *str; register int n;
  225. {
  226.     while((*str == '\t') || (*str == ' ')) str++;
  227.     if (! *str) return NULL;
  228.     while(--n) {
  229.         while ((*str != '\t') && (*str != ' ') && (*str)) str++;
  230.         if (! *str) return NULL;
  231.         while((*str == '\t') || (*str == ' ')) str++;
  232.         if (! *str) return NULL;
  233.     }
  234.     return str;
  235. }
  236.  
  237. /*
  238.  * Install the table in memory for later use.
  239.  */
  240. gettable()
  241. {
  242.     char buf[LINELEN];
  243.     register int c, n = 0;
  244.     register char *cpt;
  245.  
  246.     for (c = 0; c < NCHARS; c++) chtbl[c] = -1;
  247.  
  248. again:    if (fgets(buf, sizeof buf, in) == NULL) {
  249.         format("uud: EOF while in translation table.\n");
  250.         Error(5);
  251.     }
  252.     numl++;
  253.     if (strncmp(buf, "begin", 5) == 0) {
  254.         format("uud: Incomplete translation table.\n");
  255.         Error(6);
  256.     }
  257.     cpt = buf + strlen(buf) - 1;
  258.     *cpt = ' ';
  259.     while (*(cpt) == ' ') {
  260.         *cpt = 0;
  261.         cpt--;
  262.     }
  263.     cpt = buf;
  264.     while (c = *cpt) {
  265.         if (chtbl[c] != -1) {
  266.             format("uud: Duplicate char in translation table.\n");
  267.             Error(7);
  268.         }
  269.         if (n == 0) blank = c;
  270.         chtbl[c] = n++;
  271.         if (n >= 64) return;
  272.         cpt++;
  273.     }
  274.     goto again;
  275. }
  276.  
  277. /*
  278.  * copy from in to out, decoding as you go along.
  279.  */
  280.  
  281. decode()
  282. {
  283.     char buf[LINELEN], outl[LINELEN];
  284.     register char *bp, *ut;
  285.     register int *trtbl = chtbl;
  286.     register int n, c, rlen;
  287.     register unsigned int len;
  288.  
  289.     loop {
  290.         if (fgets(buf, sizeof buf, in) == NULL) {
  291.             format("uud: EOF before end.\n");
  292.             fclose(out);
  293.             Error(8);
  294.         }
  295.         numl++;
  296.         len = strlen(buf);
  297.         if (len) buf[--len] = '\0';
  298. /*
  299.  * Is it an unprotected empty line before the end line ?
  300.  */
  301.         if (len == 0) continue;
  302. /*
  303.  * Get the binary line length.
  304.  */
  305.         n = trtbl[*buf];
  306.         if (n >= 0) goto decod;
  307. /*
  308.  * end of uuencoded file ?
  309.  */
  310.         if (strncmp(buf, "end", 3) == 0) return;
  311. /*
  312.  * end of current file ? : get next one.
  313.  */
  314.         if (strncmp(buf, "include", 7) == 0) {
  315.             getfile(buf);
  316.             continue;
  317.         }
  318.         format("uud: Bad prefix line %d in file: %s\n",numl, ifname);
  319.         if (debug) format("Bad line =%s\n",buf);
  320.         Error(11);
  321. /*
  322.  * Sequence checking ?
  323.  */
  324. decod:        rlen = cdlen[n];
  325. /*
  326.  * Is it the empty line before the end line ?
  327.  */
  328.         if (n == 0) continue;
  329. /*
  330.  * Pad with blanks.
  331.  */
  332.         for (bp = &buf[c = len];
  333.             c < rlen; c++, bp++) *bp = blank;
  334. /*
  335.  * Verify if asked for.
  336.  */
  337.         if (debug) {
  338.             for (len = 0, bp = buf; len < rlen; len++) {
  339.                 if (trtbl[*bp] < 0) {
  340.                     format(
  341.     "Non uuencoded char <%c>, line %d in file: %s\n", *bp, numl, ifname);
  342.                     format("Bad line =%s\n",buf);
  343.                     Error(16);
  344.                 }
  345.                 bp++;
  346.             }
  347.         }
  348. /*
  349.  * All this just to check for uuencodes that append a 'z' to each line....
  350.  */
  351.         if (secnd && check) {
  352.             secnd = 0;
  353.             if (buf[rlen] == SEQMAX) {
  354.                 check = 0;
  355.                 if (debug) format("Sequence check turned off (2).\n");
  356.             } else
  357.                 if (debug) format("Sequence check on (2).\n");
  358.         } else if (first && check) {
  359.             first = 0;
  360.             secnd = 1;
  361.             if (buf[rlen] != SEQMAX) {
  362.                 check = 0;
  363.                 if (debug) format("No sequence check (1).\n");
  364.             } else
  365.                 if (debug) format("Sequence check on (1).\n");
  366.         }
  367. /*
  368.  * There we check.
  369.  */
  370.         if (check) {
  371.             if (buf[rlen] != seqc) {
  372.                 format("uud: Wrong sequence line %d in %s\n",
  373.                     numl, ifname);
  374.                 if (debug)
  375.                     format(
  376.     "Sequence char is <%c> instead of <%c>.\n", buf[rlen], seqc);
  377.                 Error(18);
  378.             }
  379.             seqc--;
  380.             if (seqc < SEQMIN) seqc = SEQMAX;
  381.         }
  382. /*
  383.  *